import { http } from "@/utils/http";
import type { ApiResponse } from "../user";
import { ensureArray, normalisePagination, toNumber } from "@/api/_helpers";

const MENU_BASE = "/system/menu";

export interface MenuNode {
  id: number;
  parent_id: number;
  name: string;
  identifier?: string;
  type?: string;
  path?: string;
  component?: string;
  redirect?: string;
  permission_code?: string | null;
  client_type?: string;
  sort?: number;
  is_visible?: number;
  status?: number;
  meta?: Record<string, any> | null;
  children?: Array<MenuNode>;
  [key: string]: any;
}

export interface MenuPayload {
  parent_id?: number;
  name: string;
  identifier: string;
  path: string;
  component?: string | null;
  redirect?: string;
  type?: string;
  permission_code?: string | null;
  client_type?: string;
  sort?: number;
  is_visible?: number;
  status?: number;
  meta?: Record<string, any> | null;
}

const mapNode = (node: Record<string, any>): MenuNode => ({
  id: toNumber(node.id, 0),
  parent_id: toNumber(node.parent_id ?? 0, 0),
  name: node.name ?? "",
  identifier: node.identifier ?? node.code ?? "",
  type: node.type ?? "menu",
  path: node.path ?? "",
  component: node.component ?? "",
  redirect: node.redirect ?? "",
  permission_code: node.permission_code ?? null,
  client_type: node.client_type ?? "admin",
  sort: toNumber(node.sort ?? node.meta?.rank ?? 0, 0),
  is_visible: toNumber(node.is_visible ?? (node.meta?.showLink ? 1 : 0), 1),
  status: toNumber(node.status ?? 1, 1),
  meta: node.meta ?? null,
  children: Array.isArray(node.children)
    ? node.children.map(mapNode)
    : undefined
});

export interface MenuListResult {
  list: Array<MenuNode>;
  pagination: {
    total: number;
    pageSize: number;
    currentPage: number;
  };
  raw?: any;
}

const fetchList = async (
  params?: Record<string, any>
): Promise<MenuListResult> => {
  const res = await http.request<ApiResponse<any>>("get", MENU_BASE, {
    params
  });
  const payload = (res?.data as Record<string, any>) ?? {};
  const listContainer =
    payload.list ??
    payload.tree ??
    payload.data ??
    payload.records ??
    payload.items ??
    [];

  const extractList = (input: unknown): Array<Record<string, any>> => {
    if (!input) return [];
    if (Array.isArray(input)) {
      return input as Array<Record<string, any>>;
    }
    if (typeof input === "object") {
      const container = input as Record<string, any>;
      for (const key of ["data", "records", "items", "list"]) {
        if (Array.isArray(container[key])) {
          return container[key] as Array<Record<string, any>>;
        }
      }
    }
    return [];
  };

  let source = extractList(listContainer);
  if (!source.length) {
    source = extractList(payload.tree);
  }
  if (!source.length) {
    source = extractList(payload.data);
  }

  source = ensureArray<Record<string, any>>(source);
  const page = toNumber(params?.page ?? 1, 1);
  const pageSizeParam = toNumber(params?.page_size ?? 0, 0);
  const fallbackPageSize =
    pageSizeParam > 0 ? pageSizeParam : source.length > 0 ? source.length : 10;

  const paginationSource =
    payload.pagination ??
    (Array.isArray(listContainer) ? undefined : listContainer);

  const pagination = normalisePagination(
    paginationSource,
    page,
    fallbackPageSize,
    source.length
  );

  return {
    list: source.map(mapNode),
    pagination: {
      total: pagination.total,
      pageSize: pagination.pageSize,
      currentPage: pagination.currentPage
    },
    raw: payload
  };
};

const create = async (payload: MenuPayload) => {
  return http.request<ApiResponse<any>>("post", MENU_BASE, {
    data: payload
  });
};

const update = async (id: number, payload: MenuPayload) => {
  return http.request<ApiResponse<any>>("put", `${MENU_BASE}/${id}`, {
    data: payload
  });
};

const remove = async (id: number) => {
  return http.request<ApiResponse<any>>("delete", `${MENU_BASE}/${id}`);
};

export default {
  fetchList,
  create,
  update,
  remove
};
